package com.smart.system.service.impl;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smart.common.config.FfmpegConfig;
import com.smart.common.constant.CacheConstants;
import com.smart.common.constant.GlobalConstants;
import com.smart.common.utils.DateUtils;
import com.smart.common.utils.modbus.ModbusUtil;
import com.smart.system.domain.Area;
import com.smart.system.domain.AreaLocation;
import com.smart.system.domain.BucketCapacityRecord;
import com.smart.system.service.IAreaService;
import com.smart.system.service.IBucketCapacityRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.system.mapper.BucketMapper;
import com.smart.system.domain.Bucket;
import com.smart.system.service.IBucketService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 垃圾桶Service业务层处理
 * 
 * @author smart
 * @date 2024-09-18
 */
@Service
public class BucketServiceImpl extends ServiceImpl<BucketMapper,Bucket> implements IBucketService {

    @Lazy
    @Autowired
    private IAreaService areaService;

    @Autowired
    private FfmpegConfig ffmpegConfig;

    @Autowired
    private IBucketCapacityRecordService bucketCapacityRecordService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 查询垃圾桶
     * 
     * @param id 垃圾桶主键
     * @return 垃圾桶
     */
    @Override
    public Bucket selectBucketById(String id)
    {
        return this.baseMapper.selectById(id);
    }

    /**
     * 查询垃圾桶列表
     *
     * @param bucketName 垃圾桶
     * @return 垃圾桶
     */
    @Override
    public IPage<Bucket> selectBucketList(String bucketName,Integer type, Page page)
    {
        return this.page(page,Wrappers.lambdaQuery(Bucket.class)
                .eq(type!=null,Bucket::getType,type)
                .like(bucketName!=null,Bucket::getName,bucketName)
                .eq(Bucket::getDelFlag, GlobalConstants.DEL_FLAG_NO)
        );
    }

    /**
     * 新增垃圾桶
     * 
     * @param bucket 垃圾桶
     * @return 结果
     */
    @Override
    public int insertBucket(Bucket bucket)
    {
        bucket.setCreateTime(DateUtils.getNowDate());
        bucket.setDelFlag(String.valueOf(GlobalConstants.DEL_FLAG_NO));
        bucket.setStatus(GlobalConstants.SUCCESS);
        return this.baseMapper.insert(bucket);
    }

    /**
     * 修改垃圾桶
     * 
     * @param bucket 垃圾桶
     * @return 结果
     */
    @Override
    public int updateBucket(Bucket bucket)
    {
        bucket.setUpdateTime(DateUtils.getNowDate());
        return this.baseMapper.updateById(bucket);
    }

    /**
     * 批量删除垃圾桶
     * 
     * @param ids 需要删除的垃圾桶主键
     * @return 结果
     */
    @Override
    public int deleteBucketByIds(String[] ids)
    {
        return this.baseMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除垃圾桶信息
     * 
     * @param id 垃圾桶主键
     * @return 结果
     */
    @Override
    public int deleteBucketById(String id)
    {
        return this.baseMapper.deleteById(id);
    }

    @Override
    public IPage<Bucket> listBucket(Integer areaId, Page toPage) {
        List<Bucket> buckets = new LinkedList<>();
        List<Bucket> list = this.list();
        //思路:先获取所有垃圾站位置,然后判断当前选取是否包含垃圾站
        if(areaId == null){
            buckets.addAll(list);
        }else{
            Area area = areaService.getById(areaId);
            for (Bucket bucket : list) {
                if (AreaLocation.isPointInPolygon(bucket.getAreaLocation(), area.getAreaLocations())) {
                    //设置已用容量
                    bucket.setUsedCapacity(bucket.getThreshold());
                    bucket.setThreshold(8);
                    bucket.setThresholdValue(3);
                    buckets.add(bucket);
                }
            }
        }

        if (buckets.size()>0) {
            List<Integer> ids = buckets.stream().map(Bucket::getId).collect(Collectors.toList());
            Page<Bucket> page = this.page(toPage,Wrappers.lambdaQuery(Bucket.class)
                    .in(ids.size()>0,Bucket::getId,ids)
                    .eq(Bucket::getDelFlag, GlobalConstants.DEL_FLAG_NO)
                    .eq(Bucket::getStatus, GlobalConstants.SUCCESS)
                    .eq(Bucket::getType, GlobalConstants.BUCKET_TYPE_BUCKET_PLATFORM)
            );
            for (Bucket record : page.getRecords()) {
                //设置已用容量
                record.setUsedCapacity(record.getThreshold());
            }
            return page;
        }
        return toPage;
    }

    @Override
    public List<String> getVideoUrl(String id) {
        Bucket bucket = this.getById(id);
        List<String> urls = new LinkedList<>();
        urls.add(ffmpegConfig.getAccessAddress()+bucket.getId()+"/1/output.m3u8");
        urls.add(ffmpegConfig.getAccessAddress()+bucket.getId()+"/2/output.m3u8");
        urls.add(ffmpegConfig.getAccessAddress()+bucket.getId()+"/3/output.m3u8");
        return urls;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean uplink(ModbusUtil.Modbus analysis) {
        // 假设原始数据范围是4-19，需要转换为0-100的百分比
        double rawValue = analysis.getDataValue();

        // 限制输入值在4-19范围内
        rawValue = Math.max(4, Math.min(19, rawValue));

        // 将4-19映射到0-100的百分比 (rawValue - 4) / (19 - 4) * 100
        int value = (int) ((rawValue - 4) / 15.0 * 100);

        Bucket bucket = this.getOne(Wrappers.lambdaQuery(Bucket.class)
                .eq(Bucket::getBucketNumber, analysis.getKey())
                .last("limit 1"));

        if (bucket == null) {
            return true;
        }

        // 如果没有变化则不修改
        if (bucket.getThreshold() != null && bucket.getThreshold() != value) {
            int newValue = Math.min(value, 100);
            // 如果变化小于等于10%则不更新
            if (Math.abs(bucket.getThreshold() - newValue) <= 10) {
                return true;
            }
            bucket.setThreshold(newValue);
            this.saveOrUpdate(bucket);

            BucketCapacityRecord bucketCapacityRecord = new BucketCapacityRecord();
            bucketCapacityRecord.setBucketId(bucket.getId());
            bucketCapacityRecord.setNumber(Math.min(value, 100));
            bucketCapacityRecord.setCreateTime(DateUtils.getNowDate());
            bucketCapacityRecordService.save(bucketCapacityRecord);
        }

        return true;
    }
}
